#include <iostream>
#include <cstring>
using namespace std;

const int N = 1000010;
const int INF = 0x3f3f3f3f;
int h[N], e[N * 2], ne[N * 2], w[N * 2], idx = 0; //邻接表，因为是无向图，所以点之间可能都是双边，所以这里开了N*2
int heap[N], ph[N], hp[N], Size = 0;              //堆,heap[ph[k]]表示点k到达集合的距离
int dist[N];                                      //存储到集合的距离
bool st[N];                                       //存储是否已经加入集合
int n, m, a, b, c;                                //获取输入

void h_swap(int a, int b) //模拟堆的两个结点交换
{
    swap(ph[hp[a]], ph[hp[b]]); //先由堆中存储边长的结点的编号索引到的图中对应的要到达的点的编号，再由找到的编号找到反向索引数组，防止交换以后找不到
    swap(hp[a], hp[b]);         //再交换堆中存储边长的结点索引邻接表编号的数组
    swap(heap[a], heap[b]);     //最后交换邻接表中存储的值
    return;
}

void up(int u) //将堆中的某个结点尽可能的往上移动
{
    while (u / 2 && heap[u / 2] > heap[u]) //由于创建的是小根堆，所以如果我比我上面的大，那就和上面的交换
    {
        h_swap(u / 2, u);
        u >>= 1;
    }
    return;
}

void down(int u) //将堆中的某个结点尽可能的往下移
{
    int t = u;
    if (2 * u <= Size && heap[2 * u] < heap[t])
        t = 2 * u;
    if (2 * u + 1 <= Size && heap[2 * u + 1] < heap[t])
        t = 2 * u + 1;
    if (t != u)
    {
        h_swap(t, u);
        down(t);
    }
    return;
}

void h_add(int k, int x) //将到结点k的距离为x这一信息入堆
{
    Size++;
    heap[Size] = x;
    hp[Size] = k;
    ph[k] = Size;
    up(Size);
    return;
}

void del(int k) //将点k从堆中删除
{
    k = ph[k];
    h_swap(k, Size);
    Size--;
    up(k);
    down(k);
    return;
}

void add(int x, int y, int z) //将x到y距离为z这一信息加入邻接表
{
    e[idx] = y;
    w[idx] = z;
    ne[idx] = h[x];
    h[x] = idx++;
    return;
}

void alter(int k, int x)
{
    heap[ph[k]] = x;
    up(ph[k]);
    down(ph[k]);
    return;
}

int prim()
{
    int res = 0;
    int num = 0;
    dist[1] = 0;
    h_add(1, dist[1]);
    while (Size)
    {
        int t = hp[1];  //找到现阶段还未进树的距离树集合最小的点
        st[t] = true;   //将其标记为已进入树
        res += dist[t]; //将其到树的距离进行更新
        num++;          //又多了一个入树的点
        del(t);         //将这个点删除
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (!st[j] && dist[j] > w[i])
            {
                dist[j] = w[i];
                if (!ph[j]) //如果j没入过堆，则入堆
                    h_add(j, dist[j]);
                else //不然就在堆里面修改它
                    alter(j, dist[j]);
            }
        }
    }
    if (num != n)
        return INF;
    else
        return res;
}

int main()
{
    memset(h, -1, sizeof h);
    memset(dist, 0x3f, sizeof dist);
    memset(st, false, sizeof st);
    cin >> n >> m;
    while (m--)
    {
        cin >> a >> b >> c;
        add(a, b, c);
        add(b, a, c);
    }
    int t = prim();
    if (t == INF)
        cout << "impossible";
    else
        cout << t;
    return 0;
}